home *** CD-ROM | disk | FTP | other *** search
/ Compendium Deluxe 1 / LSD Compendium Deluxe 1.iso / a / programming / assembly / iff2pc.lha / paz / IFF-8SVX.s next >
Encoding:
Text File  |  1993-04-18  |  16.5 KB  |  719 lines

  1.  
  2.     opt o-,d-
  3.  
  4.     incdir    "Includes:"
  5.     include    "misc/DevpacMacros.i"
  6.     include    "misc/DeliPlayer.i"
  7.     include    "exec/exec.i"
  8.     include    "exec/io.i"
  9.     include    "devices/audio.i"
  10.  
  11.  
  12. Left_0        EQU 1                ; Audiokanal 1
  13. Right_1        EQU 2                ; Audiokanal 2
  14. Right_2        EQU 4                ; Audiokanal 3
  15. Left_3        EQU 8                ; Audiokanal 4
  16.  
  17. FORM        EQU ('F'<<24)!('O'<<16)!('R'<<8)!('M')
  18. ID_8SVX        EQU ('8'<<24)!('S'<<16)!('V'<<8)!('X')
  19. ID_VHDR        EQU ('V'<<24)!('H'<<16)!('D'<<8)!('R')
  20. ID_CHAN        EQU ('C'<<24)!('H'<<16)!('A'<<8)!('N')
  21. ID_SEQN        EQU ('S'<<24)!('E'<<16)!('Q'<<8)!('N')
  22. ID_FADE        EQU ('F'<<24)!('A'<<16)!('D'<<8)!('E')
  23. ID_BODY        EQU ('B'<<24)!('O'<<16)!('D'<<8)!('Y')
  24.  
  25. sCmpNone    EQU 0
  26.  
  27. sCompression    EQU 15
  28. samplesPerSec    EQU 12
  29.  
  30. sampletype    EQU 0
  31. LEFT        EQU 2
  32. RIGHT        EQU 4
  33. STEREO        EQU 6
  34.  
  35.  
  36. *-----------------------------------------------------------------------*
  37.  
  38.     STRUCTURE    DeliPlayMsg,MN_SIZE
  39.     APTR    dpm_Command
  40.     LONG    dpm_UserData
  41.     LABEL    dpm_SIZEOF
  42.  
  43. *-----------------------------------------------------------------------*
  44.  
  45.  
  46. ;
  47. ;
  48.     SECTION Player,Code
  49. ;
  50. ;
  51.  
  52.     PLAYERHEADER PlayerTagArray
  53.  
  54.     dc.b '$VER: IFF-8SVX player module V1.4 (02 Mar 93)',0
  55.     even
  56.  
  57. PlayerTagArray
  58.     dc.l    DTP_PlayerVersion,3
  59.     dc.l    DTP_PlayerName,PName
  60.     dc.l    DTP_Creator,CName
  61.     dc.l    DTP_Check2,Chk
  62.     dc.l    DTP_InitPlayer,InitPlay
  63.     dc.l    DTP_EndPlayer,EndPlay
  64.     dc.l    DTP_StartInt,StartSnd
  65.     dc.l    DTP_StopInt,StopSnd
  66.     dc.l    DTP_Volume,SetVol
  67.     dc.l    DTP_Balance,SetVol
  68.     dc.l    TAG_DONE
  69.  
  70. *-----------------------------------------------------------------------*
  71. ;
  72. ; Player/Creatorname und lokale Daten
  73.  
  74. PName        dc.b 'IFF-8SVX',0
  75.  
  76. CName        dc.b 'Frank Riffel and Peter Kunath in 1993',0
  77.  
  78. TaskName    dc.b 'IFF-8SVX_Player',0
  79. DeliPortName    dc.b '8SVX->Player',0
  80. PlayerPortName    dc.b '8SVX<-Player',0
  81. AudioPortName    dc.b '8SVX_Player',0
  82. audioname    dc.b 'audio.device',0
  83. ChannelMap    dc.b Left_0!Right_1
  84.         dc.b Left_0!Right_2
  85.         dc.b Left_3!Right_1
  86.         dc.b Left_3!Right_2
  87.     even
  88.  
  89. _DOSBase    dc.l 0
  90. SongendPtr    dc.l 0
  91. QuitFlag    dc.w 0
  92.  
  93. s_adr        dc.l 0            ; Startaddress
  94. s_end        dc.l 0            ; Endaddress
  95. s_size        dc.l 0            ; Samplesize
  96. s_speed        dc.w 0            ; Initial Speed
  97. s_chan1        dc.l 0            ; channel 1
  98. s_chan2        dc.l 0            ; channel 2
  99.  
  100. p_chmap        dc.l 0            ; channelmap
  101. p_size        dc.l 0            ; Samplesize
  102. p_pos        dc.l 0            ; Position in sample
  103. p_len        dc.l 0            ; Length of sampleblock
  104. p_speed        dc.w 0            ; see above ... for playing
  105. p_chan1        dc.l 0            ; channel 1
  106. p_chan2        dc.l 0            ; channel 2
  107. p_l_vol        dc.w 0            ; left volume
  108. p_r_vol        dc.w 0            ; right volume
  109. p_wmsg        dc.w 0            ; write message counter
  110. p_pause        dc.w 0            ; playing/paused
  111. p_endpos    dc.l 0            ; songend
  112.  
  113. p_ioreq1    dc.l IORequest1a
  114. p_ioreq1b    dc.l IORequest1b
  115. p_ioreq2    dc.l IORequest2a
  116. p_ioreq2b    dc.l IORequest2b
  117.  
  118. PlayerPort    dcb.b MP_SIZE,0
  119. DeliPort    dcb.b MP_SIZE,0
  120.  
  121. DeliMsg        dcb.b dpm_SIZEOF,0
  122.  
  123. AudioPort    dcb.b MP_SIZE,0
  124.  
  125. IORequest    dcb.b ioa_SIZEOF,0
  126. IORequest1a    dcb.b ioa_SIZEOF,0
  127. IORequest1b    dcb.b ioa_SIZEOF,0
  128. IORequest2a    dcb.b ioa_SIZEOF,0
  129. IORequest2b    dcb.b ioa_SIZEOF,0
  130.  
  131. *-----------------------------------------------------------------------*
  132. ;
  133. ; Testet auf IFF 8SVX
  134.  
  135. Chk
  136.     move.l    dtg_ChkData(a5),a0
  137.  
  138.     cmpi.l    #FORM,(a0)+            ; right file type ?
  139.     bne    ChkErr                ; no IFF File at all
  140.     move.l    (a0)+,a1            ; size
  141.     cmp.l    dtg_ChkSize(a5),a1
  142.     bgt    ChkErr                ; file is too small
  143.     add.l    a0,a1                ; calculate last address
  144.     move.l    a1,s_end            ; end address in memory
  145.  
  146.     cmpi.l    #ID_8SVX,(a0)+            ; is it a 8SVX sample file?
  147.     bne    ChkErr                ; no
  148.     move.l    a0,s_adr            ; start address in memory
  149.  
  150.     move.l    #ID_VHDR,d0            ; find VHDR chunk
  151.     move.l    s_adr,a0            ; start address
  152.     move.l    s_end,a1            ; end address
  153.     bsr.s    FindChunk            ; search chunk
  154.     tst.l    d0                ; test result
  155.     beq.s    ChkErr                ; this file must be mangled!
  156.  
  157.     addq.l    #4,a0                ; skip chunk length
  158.     cmpi.b    #sCmpNone,sCompression(a0)    ; is the sample packed?
  159.     bne.s    ChkErr                ; packing is not supported yet
  160.     move.w    samplesPerSec(a0),s_speed    ; samples per second
  161.  
  162.     moveq    #0,d2                ; sample is mono (default)
  163.  
  164.     move.l    #ID_CHAN,d0            ; find CHAN chunk
  165.     move.l    s_adr,a0            ; start address
  166.     move.l    s_end,a1            ; end address
  167.     bsr.s    FindChunk            ; search chunk
  168.     tst.l    d0                ; test result
  169.     beq.s    ChkNoChan            ; sorry, no chan chunk found
  170.  
  171.     addq.l    #4,a0                ; skip chunk length
  172.     cmpi.l    #STEREO,sampletype(a0)        ; type of sample ?
  173.     bne.s    ChkNoChan            ; LEFT and RIGHT are ignored and it
  174.     moveq    #1,d2                ; is played in mono on both speakers
  175. ChkNoChan
  176.     move.l    #ID_BODY,d0            ; find BODY chunk
  177.     move.l    s_adr,a0            ; start address
  178.     move.l    s_end,a1            ; end address
  179.     bsr.s    FindChunk            ; search chunk
  180.     tst.l    d0                ; test result
  181.     beq.s    ChkErr                ; sorry, no body chunk found
  182.  
  183.     move.l    (a0)+,d1            ; chunk size
  184.     lsr.l    d2,d1                ; halfe size if stereo
  185.     move.l    d1,s_size            ; save size of the sample
  186.     move.l    a0,s_chan1            ; waveform data for channel 1
  187.     neg.l    d2                ; build mask
  188.     and.l    d2,d1                ; same data if mono
  189.     add.l    d1,a0                ; add size
  190.     move.l    a0,s_chan2            ; waveform data for channel 2
  191.  
  192.     moveq    #0,d0                ; it is a sample!
  193.     bra.s    ChkEnd
  194. ChkErr
  195.     moveq    #-1,d0                ; not a sample !
  196. ChkEnd
  197.     rts
  198.  
  199. ;-----------------------------------------------------------------------
  200. ;
  201. ; This function finds the given chunk and skips all others in between!
  202. ;
  203. ; in:    d0.l ChunkID
  204. ;    a0.l StartPosition
  205. ;    a1.l LastPosition
  206. ;
  207. ; out:    a0.l ChunkStart if not found NULL
  208.  
  209. FindChunk
  210.     cmp.l    (a0)+,d0            ; is this the searched chunk ?
  211.     beq.s    Found                ; yes !
  212.     adda.l    (a0)+,a0            ; no, then skip this chunk
  213.     cmpa.l    a0,a1                ; are we behind the mem limit ?
  214.     bgt.s    FindChunk            ; no, search until error or success
  215.     suba.l    a0,a0                ; we are behind the limits
  216.     moveq    #0,d0                ; errorflag
  217. Found    rts                    ; exit this routine
  218.  
  219. *-----------------------------------------------------------------------*
  220. ;
  221. ; Init Player
  222.  
  223. InitPlay
  224.     move.l    dtg_DOSBase(a5),_DOSBase    ; DOS
  225.  
  226.     move.l    dtg_SongEnd(a5),SongendPtr    ; store Songend FunctionPtr
  227.  
  228.     lea    PlayerPort(pc),a0        ; init Port
  229.     clr.l    LN_SUCC(a0)
  230.     clr.l    LN_PRED(a0)
  231.     move.b    #NT_MSGPORT,LN_TYPE(a0)
  232.     clr.b    LN_PRI(a0)
  233.     move.l    #PlayerPortName,LN_NAME(a0)
  234.     move.b    #PA_SIGNAL,MP_FLAGS(a0)
  235.  
  236.     moveq    #-1,d0
  237.     CALLEXEC AllocSignal            ; Signalbit für PlayerPort besorgen
  238.     lea    PlayerPort(pc),a1        ; ^Port
  239.     move.b    d0,MP_SIGBIT(a1)
  240.     move.l    ThisTask(a6),MP_SIGTASK(a1)    ; copy ^ThisTask
  241.     CALLEXEC AddPort            ; MsgPort anlegen
  242.  
  243.     move.l    #TaskName,d1            ; name
  244.     moveq    #10,d2                ; pri
  245.     lea    PlayerProc(pc),a0        ; ^segment
  246.     move.l    a0,d3
  247.     lsr.l    #2,d3                ; APTR -> BPTR
  248.     move.l    #4096,d4            ; stack
  249.     CALLDOS CreateProc            ; start a new process
  250.     tst.l    d0
  251.     beq.s    EndPlay2            ; error
  252.  
  253.     lea    PlayerPort(pc),a0
  254.     CALLEXEC WaitPort            ; Schlaf gut
  255.  
  256.     lea    PlayerPort(pc),a0
  257.     CALLEXEC GetMsg
  258.  
  259.     move.l    d0,a0                ; Message
  260.     move.l    dpm_UserData(a0),d0        ; set returnvalue
  261.     bne.s    EndPlay2            ; error
  262.     rts
  263.  
  264. *-----------------------------------------------------------------------*
  265. ;
  266. ; End Player
  267.  
  268. EndPlay
  269.     lea    DeliPort(pc),a0
  270.     lea    DeliMsg(pc),a1
  271.     move.l    #PlayerPort,MN_REPLYPORT(a1)
  272.     move.w    #dpm_SIZEOF,MN_LENGTH(a1)
  273.     move.l    #EndPlayer,dpm_Command(a1)
  274.     CALLEXEC PutMsg
  275.  
  276.     lea    PlayerPort(pc),a0
  277.     CALLEXEC WaitPort            ; Schlaf gut
  278.  
  279.     lea    PlayerPort(pc),a0
  280.     CALLEXEC GetMsg
  281. EndPlay2
  282.     lea    PlayerPort(pc),a1
  283.     CALLEXEC RemPort            ; MsgPort entfernen
  284.     lea    PlayerPort(pc),a1
  285.     move.b    MP_SIGBIT(a1),d0
  286.     CALLEXEC FreeSignal            ; Signalbit für PlayerPort freigeben
  287.  
  288.     moveq    #-1,d0                ; set error
  289.     rts
  290.  
  291. *-----------------------------------------------------------------------*
  292. ;
  293. ; Start Sound
  294.  
  295. StartSnd
  296.     lea    DeliPort(pc),a0
  297.     lea    DeliMsg(pc),a1
  298.     move.l    #PlayerPort,MN_REPLYPORT(a1)
  299.     move.w    #dpm_SIZEOF,MN_LENGTH(a1)
  300.     move.l    #StartSound,dpm_Command(a1)
  301.     CALLEXEC PutMsg
  302.  
  303.     lea    PlayerPort(pc),a0
  304.     CALLEXEC WaitPort            ; Schlaf gut
  305.  
  306.     lea    PlayerPort(pc),a0
  307.     CALLEXEC GetMsg
  308.     rts
  309.  
  310. *-----------------------------------------------------------------------*
  311. ;
  312. ; Stop Sound
  313.  
  314. StopSnd
  315.     lea    DeliPort(pc),a0
  316.     lea    DeliMsg(pc),a1
  317.     move.l    #PlayerPort,MN_REPLYPORT(a1)
  318.     move.w    #dpm_SIZEOF,MN_LENGTH(a1)
  319.     move.l    #StopSound,dpm_Command(a1)
  320.     CALLEXEC PutMsg
  321.  
  322.     lea    PlayerPort(pc),a0
  323.     CALLEXEC WaitPort            ; Schlaf gut
  324.  
  325.     lea    PlayerPort(pc),a0
  326.     CALLEXEC GetMsg
  327.     rts
  328.  
  329. *-----------------------------------------------------------------------*
  330. ;
  331. ; Set Volume & Balance
  332.  
  333. SetVol
  334.     move.w    dtg_SndLBal(a5),d0
  335.     mulu    dtg_SndVol(a5),d0
  336.     lsr.w    #6,d0
  337.     move.w    d0,p_l_vol            ; Left Volume
  338.  
  339.     move.w    dtg_SndRBal(a5),d0
  340.     mulu    dtg_SndVol(a5),d0
  341.     lsr.w    #6,d0
  342.     move.w    d0,p_r_vol            ; Right Volume
  343.  
  344.     lea    DeliPort(pc),a0
  345.     lea    DeliMsg(pc),a1
  346.     move.l    #PlayerPort,MN_REPLYPORT(a1)
  347.     move.w    #dpm_SIZEOF,MN_LENGTH(a1)
  348.     move.l    #SetVolume,dpm_Command(a1)
  349.     CALLEXEC PutMsg
  350.  
  351.     lea    PlayerPort(pc),a0
  352.     CALLEXEC WaitPort            ; Schlaf gut
  353.  
  354.     lea    PlayerPort(pc),a0
  355.     CALLEXEC GetMsg
  356.     rts
  357.  
  358. *-----------------------------------------------------------------------*
  359. ;
  360. ; Player Process
  361.  
  362.     cnop 0,4                ; Align to longword
  363. PlayerProc
  364.     dc.l    16                ; Segment "length" (faked)
  365.     dc.l    0                ; Pointer to next segment
  366.  
  367. Begin
  368.     lea    DeliPort(pc),a0            ; init Port
  369.     clr.l    LN_SUCC(a0)
  370.     clr.l    LN_PRED(a0)
  371.     move.b    #NT_MSGPORT,LN_TYPE(a0)
  372.     clr.b    LN_PRI(a0)
  373.     move.l    #DeliPortName,LN_NAME(a0)
  374.     move.b    #PA_SIGNAL,MP_FLAGS(a0)
  375.  
  376.     moveq    #-1,d0
  377.     CALLEXEC AllocSignal            ; Signalbit für DeliPort besorgen
  378.     lea    DeliPort(pc),a1            ; ^Port
  379.     move.b    d0,MP_SIGBIT(a1)
  380.     move.l    ThisTask(a6),MP_SIGTASK(a1)    ; copy ^ThisTask
  381.     CALLEXEC AddPort            ; MsgPort anlegen
  382.  
  383.     lea    AudioPort(pc),a0        ; init Port
  384.     clr.l    LN_SUCC(a0)
  385.     clr.l    LN_PRED(a0)
  386.     move.b    #NT_MSGPORT,LN_TYPE(a0)
  387.     clr.b    LN_PRI(a0)
  388.     move.l    #AudioPortName,LN_NAME(a0)
  389.     move.b    #PA_SIGNAL,MP_FLAGS(a0)
  390.  
  391.     lea    IORequest(pc),a0        ; init IORequest
  392.     clr.l    LN_SUCC(a0)
  393.     clr.l    LN_PRED(a0)
  394.     clr.b    LN_TYPE(a0)
  395.     move.b    #ADALLOC_MAXPREC,LN_PRI(a0)
  396.     clr.l    LN_NAME(a0)
  397.     move.l    #AudioPort,MN_REPLYPORT(a0)
  398.  
  399.     moveq    #-1,d0
  400.     CALLEXEC AllocSignal            ; Signalbit für AudioPort besorgen
  401.     lea    AudioPort(pc),a1        ; ^Port
  402.     move.b    d0,MP_SIGBIT(a1)    
  403.     move.l    ThisTask(a6),MP_SIGTASK(a1)    ; copy ^ThisTask
  404.     CALLEXEC AddPort            ; MsgPort für AudioDevice anlegen
  405.  
  406.     moveq    #0,d0                ; AudioDevice öffnen
  407.     moveq    #0,d1                
  408.     lea    audioname(pc),a0
  409.     lea    IORequest(pc),a1        ; IORequeststruktur
  410.  
  411.     clr.l    IO_UNIT(a1)            ; (re-)init structure
  412.     move.w    #ADCMD_ALLOCATE,IO_COMMAND(a1)
  413.     move.b    #ADIOF_NOWAIT,IO_FLAGS(a1)
  414.     clr.b    IO_ERROR(a1)
  415.     move.l    #ChannelMap,ioa_Data(a1)
  416.     move.l    #4,ioa_Length(a1)
  417.     clr.w    ioa_Period(a1)
  418.     clr.w    ioa_Volume(a1)
  419.     clr.w    ioa_Cycles(a1)
  420.  
  421.     CALLEXEC OpenDevice
  422.  
  423.     lea    DeliMsg(pc),a0            ; Message
  424.     clr.l    MN_REPLYPORT(a0)
  425.     move.w    #dpm_SIZEOF,MN_LENGTH(a0)
  426.     move.l    d0,dpm_UserData(a0)        ; set retunvalue
  427.  
  428.     lea    IORequest(pc),a0        ; IORequeststruktur
  429.     move.l    IO_UNIT(a0),p_chmap        ; store Channelmap
  430.  
  431.     lea    AudioPort(pc),a1        ; Audio Port
  432.  
  433.     move.l    IO_DEVICE(a0),d0        ; get ^Device & AllocKey
  434.     move.w    ioa_AllocKey(a0),d1
  435.  
  436.     lea    IORequest1a(pc),a0
  437.     bsr    InitIORequest            ; IORequest 1a
  438.  
  439.     lea    IORequest1b(pc),a0
  440.     bsr    InitIORequest            ; IORequest 1b
  441.  
  442.     lea    IORequest2a(pc),a0
  443.     bsr    InitIORequest            ; IORequest 2a
  444.  
  445.     lea    IORequest2b(pc),a0
  446.     bsr    InitIORequest            ; IORequest 2b
  447.  
  448.     move.l    #3579547,d0            ; copy & convert chk values
  449.     divu    s_speed,d0
  450.     move.w    d0,p_speed
  451.     move.l    s_size,p_size
  452.     move.l    s_chan1,p_chan1
  453.     move.l    s_chan2,p_chan2
  454.  
  455.     move.w    #-1,QuitFlag            ; kein Ende
  456.     move.w    #-1,p_pause            ; paused
  457.  
  458.     lea    PlayerPort(pc),a0
  459.     lea    DeliMsg(pc),a1            ; Message
  460.     CALLEXEC PutMsg                ; player is ready !
  461.  
  462.     lea    DeliMsg(pc),a0
  463.     tst.l    dpm_UserData(a0)        ; initialisation error ?
  464.     bne    NoAudioDev            ; yes !
  465.  
  466. ;--------------------------------------------------------------------------
  467. ;
  468. ; Hauptschleife
  469.  
  470. MainLoop
  471.     bsr    PlaySample
  472.  
  473.     moveq    #0,d0                ; clear WaitMask
  474.  
  475.     lea    AudioPort(pc),a0
  476.     move.b    MP_SIGBIT(a0),d1        ; AudioMask holen
  477.     bset.l    d1,d0
  478.  
  479.     lea    DeliPort(pc),a0
  480.     move.b    MP_SIGBIT(a0),d1        ; DeliMask holen
  481.     bset.l    d1,d0
  482.  
  483.     CALLEXEC Wait                ; Schlaf gut
  484.  
  485. AudioCollect                    ; collects Write msg's
  486.     lea    AudioPort(pc),a0
  487.     CALLEXEC GetMsg
  488.     tst.l    d0                ; Msg da ?
  489.     beq.s    DeliCollect            ; Nein !
  490.     subq.w    #1,p_wmsg            ; Messagecounter - 1
  491.     bra.s    AudioCollect
  492.  
  493. DeliCollect                    ; collects DeliTracker msg's
  494.     lea    DeliPort(pc),a0
  495.     CALLEXEC GetMsg
  496.     tst.l    d0                ; Msg da ?
  497.     beq.s    DeliSelect            ; Nein !
  498.     move.l    d0,-(sp)            ; store ^Msg
  499.     move.l    d0,a0
  500.     move.l    dpm_Command(a0),a0        ; CMD
  501.     jsr    (a0)                ; Befehl ausführen
  502.     move.l    (sp)+,a1            ; restore ^Msg
  503.     CALLEXEC ReplyMsg            ; return to sender
  504.     bra.s    DeliCollect
  505.  
  506. DeliSelect
  507.     tst.w    QuitFlag            ; schon Ende ?
  508.     bne.s    MainLoop            ; noch nicht !
  509.  
  510. ;--------------------------------------------------------------------------
  511. ;
  512. ; quit Player
  513.  
  514. Quit
  515.     lea    IORequest(pc),a1        ; Audio Device schließen
  516.     CALLEXEC CloseDevice
  517. NoAudioDev
  518.     lea    AudioPort(pc),a1
  519.     CALLEXEC RemPort            ; MsgPort für AudioDevice entfernen
  520.     lea    AudioPort(pc),a1
  521.     move.b    MP_SIGBIT(a1),d0
  522.     CALLEXEC FreeSignal            ; Signalbit für AudioPort freigeben
  523.  
  524.     lea    DeliPort(pc),a1
  525.     CALLEXEC RemPort            ; MsgPort entfernen
  526.     lea    DeliPort(pc),a1
  527.     move.b    MP_SIGBIT(a1),d0
  528.     CALLEXEC FreeSignal            ; Signalbit für DeliPort freigeben
  529.  
  530.     rts                    ; Playerprozess beenden
  531.  
  532. ;--------------------------------------------------------------------------
  533. ;
  534. ; End Player
  535.  
  536. EndPlayer
  537.     clr.w    QuitFlag            ; Player beenden
  538.     rts
  539.  
  540. ;--------------------------------------------------------------------------
  541. ;
  542. ; Init IORequest
  543. ;
  544. ; in: a0:^iorequest
  545. ;     a1:^port
  546. ;     d0:Device
  547. ;     d1:AllocKey
  548.  
  549. InitIORequest
  550.     move.b    #ADALLOC_MAXPREC,LN_PRI(a0)
  551.     clr.l    LN_NAME(a0)
  552.     move.l    a1,MN_REPLYPORT(a0)
  553.     move.l    d0,IO_DEVICE(a0)
  554.     clr.l    IO_UNIT(a0)
  555.     clr.w    IO_COMMAND(a0)
  556.     clr.b    IO_FLAGS(a0)
  557.     clr.b    IO_ERROR(a0)
  558.     move.w    d1,ioa_AllocKey(a0)
  559.     clr.l    ioa_Data(a0)
  560.     clr.l    ioa_Length(a0)
  561.     clr.w    ioa_Period(a0)
  562.     clr.w    ioa_Volume(a0)
  563.     clr.w    ioa_Cycles(a0)
  564.     rts
  565.  
  566. *-----------------------------------------------------------------------*
  567. ;
  568. ; Start Sound
  569.  
  570. StartSound
  571.     tst.w    p_pause                ; playing/paused ?
  572.     beq.s    StSnd_End            ; playing !
  573.  
  574.     clr.w    p_pause                ; playing
  575.     clr.l    p_pos                ; start from begin
  576.  
  577.     lea    IORequest(pc),a1
  578.     move.l    p_chmap(pc),IO_UNIT(a1)        ; stop both channels
  579.     move.w    #CMD_STOP,IO_COMMAND(a1)
  580.     move.b    #IOF_QUICK,IO_FLAGS(a1)
  581.     BEGINIO                    ; execute command
  582.  
  583.     bsr    SetVolume            ; Lautstärke setzen
  584.  
  585.     bsr    DoubleBuff            ; Sound zweimal starten
  586.     bsr    DoubleBuff            ; (wegen Double Buffering)
  587.  
  588.     lea    IORequest(pc),a1
  589.     move.l    p_chmap(pc),IO_UNIT(a1)        ; start both channels
  590.     move.w    #CMD_START,IO_COMMAND(a1)
  591.     move.b    #IOF_QUICK,IO_FLAGS(a1)
  592.     BEGINIO                    ; execute command
  593. StSnd_End
  594.     rts
  595.  
  596. *-----------------------------------------------------------------------*
  597. ;
  598. ; Plays the Sample
  599.  
  600. PlaySample
  601.     tst.w    p_pause                ; playing/paused ?
  602.     bne    PlSam_End            ; paused !
  603.  
  604.     tst.w    p_wmsg                ; all write msg's replied ?
  605.     bgt    PlSam_End            ; no !
  606.  
  607.     tst.l    p_endpos            ; songend reached ?
  608.     bne.s    DoubleBuff            ; no !
  609.     move.l    SongendPtr(pc),a0
  610.     jsr    (a0)                ; signal songend to DeliTracker
  611. DoubleBuff
  612.     move.w    #2,p_wmsg            ; 2 write msg's are pending
  613.  
  614.     move.l    p_size(pc),d0
  615.     sub.l    p_pos(pc),d0
  616.     cmpi.l    #128*1024,d0
  617.     ble.s    SmallSample
  618.     move.l    #128*1024,d0
  619. SmallSample
  620.     move.l    d0,p_len
  621.  
  622.     move.l    p_ioreq1(pc),a1
  623.     move.l    p_chmap(pc),d0
  624.     andi.l    #Left_0!Left_3,d0
  625.     move.l    d0,IO_UNIT(a1)            ; Channel 1
  626.     move.w    #CMD_WRITE,IO_COMMAND(a1)
  627.     move.b    #IOF_QUICK,IO_FLAGS(a1)
  628.     move.l    p_chan1(pc),d0
  629.     add.l    p_pos(pc),d0
  630.     move.l    d0,ioa_Data(a1)
  631.     move.l    p_len(pc),ioa_Length(a1)
  632.     move.w    #1,ioa_Cycles(a1)
  633.     BEGINIO                    ; execute command
  634.  
  635.     move.l    p_ioreq1(pc),d0            ; swap ^ioreq
  636.     move.l    p_ioreq1b(pc),p_ioreq1
  637.     move.l    d0,p_ioreq1b
  638.  
  639.     move.l    p_ioreq2(pc),a1
  640.     move.l    p_chmap(pc),d0
  641.     andi.l    #Right_1!Right_2,d0
  642.     move.l    d0,IO_UNIT(a1)            ; Channel 2
  643.     move.w    #CMD_WRITE,IO_COMMAND(a1)
  644.     move.b    #IOF_QUICK,IO_FLAGS(a1)
  645.     move.l    p_chan2(pc),d0
  646.     add.l    p_pos(pc),d0
  647.     move.l    d0,ioa_Data(a1)
  648.     move.l    p_len(pc),ioa_Length(a1)
  649.     move.w    #1,ioa_Cycles(a1)
  650.     BEGINIO                    ; execute command
  651.  
  652.     move.l    p_ioreq2(pc),d0            ; swap ^ioreq
  653.     move.l    p_ioreq2b(pc),p_ioreq2
  654.     move.l    d0,p_ioreq2b
  655.  
  656.     move.l    p_pos(pc),p_endpos
  657.  
  658.     move.l    p_len(pc),d0
  659.     add.l    p_pos(pc),d0
  660.     cmp.l    p_size(pc),d0
  661.     blt.s    NextSampleBlock
  662.     moveq    #0,d0
  663. NextSampleBlock
  664.     move.l    d0,p_pos
  665.  
  666. PlSam_End
  667.     rts
  668.  
  669. *-----------------------------------------------------------------------*
  670. ;
  671. ; Stop Sound
  672.  
  673. StopSound
  674.     tst.w    p_pause                ; playing/paused ?
  675.     bne.s    SpSnd_End            ; paused !
  676.  
  677.     move.w    #-1,p_pause            ; paused
  678.  
  679.     lea    IORequest(pc),a1
  680.     move.l    p_chmap(pc),IO_UNIT(a1)        ; both Channels
  681.     move.w    #CMD_FLUSH,IO_COMMAND(a1)
  682.     move.b    #IOF_QUICK,IO_FLAGS(a1)
  683.     BEGINIO                    ; execute command
  684. SpSnd_End
  685.     rts
  686.  
  687. *-----------------------------------------------------------------------*
  688. ;
  689. ; Set Volume & Balance
  690.  
  691. SetVolume
  692.     tst.w    p_pause                ; playing/paused ?
  693.     bne.s    StVol_End            ; paused !
  694.  
  695.     lea    IORequest(pc),a1
  696.     move.l    p_chmap(pc),d0
  697.     andi.l    #Left_0!Left_3,d0
  698.     move.l    d0,IO_UNIT(a1)            ; Channel 1
  699.     move.w    #ADCMD_PERVOL,IO_COMMAND(a1)
  700.     move.b    #IOF_QUICK,IO_FLAGS(a1)
  701.     move.w    p_speed(pc),ioa_Period(a1)
  702.     move.w    p_l_vol(pc),ioa_Volume(a1)    ; Left Volume
  703.     BEGINIO                    ; execute command
  704.  
  705.     lea    IORequest(pc),a1
  706.     move.l    p_chmap(pc),d0
  707.     andi.l    #Right_1!Right_2,d0
  708.     move.l    d0,IO_UNIT(a1)            ; Channel 2
  709.     move.w    #ADCMD_PERVOL,IO_COMMAND(a1)
  710.     move.b    #IOF_QUICK,IO_FLAGS(a1)
  711.     move.w    p_speed(pc),ioa_Period(a1)
  712.     move.w    p_r_vol(pc),ioa_Volume(a1)    ; Right Volume
  713.     BEGINIO                    ; execute command
  714. StVol_End
  715.     rts
  716.  
  717. *-----------------------------------------------------------------------*
  718.  
  719.